const {v4: uuidv4} = require('uuid')
const Tasks = require('../../models/tasks')

const getAllTasksHandler = async (req, res) => {
  try {
    const {id: userId} = req.user

    const tasks = await Tasks.aggregate([
      {
        $lookup: {
          from: 'tasks',
          localField: 'id',
          foreignField: 'parentId',
          as: 'tasks',
        },
      },
      {
        $match: {
          parentId: '',
          userId: userId,
          projectId: 'user',
        },
      },
    ])
    // tasks.length
    res.status(200).json(tasks)
    // : res.status(404).json({success: false, msg: 'Документы не найдены'})
  } catch (e) {
    res.status(500).json({success: false, msg: e})
  }
}

const getAllSubTasksHandler = async (_, res) => {
  try {
    const tasks = await Tasks.find({isSubtask: false})
    tasks.length
      ? res.status(200).json(tasks)
      : res.status(404).json({success: false, msg: 'Документы не найдены'})
  } catch (e) {
    res.status(500).json({success: false, msg: e})
  }
}

const getTaskHandler = async (req, res) => {
  const {id} = req.params
  try {
    const tasks = await Tasks.find({id: id})
    tasks.length
      ? res.status(200).json(tasks[0])
      : res.status(404).json({success: false, msg: 'Документ не найден'})
  } catch (e) {
    res.status(500).json({success: false, msg: e})
  }
}

const getSubTaskHandler = async (req, res) => {
  const {id} = req.params
  try {
    const tasks = await Tasks.find({parentId: id})
    tasks.length
      ? res.status(200).json(tasks)
      : res.status(404).json({success: false, msg: 'Документы не найдены'})
  } catch (e) {
    res.status(500).json({success: false, msg: e})
  }
}

const postNewTaskHandler = async (req, res) => {
  const {task, subtasks} = req.body
  const parentId = uuidv4()
  const arr = []
  const {title, text, deadlineDate, type, tagsIds, projectId, userId} = task

  arr.push({
    id: parentId,
    title,
    text,
    startDate: new Date(),
    deadlineDate,
    type,
    tagsIds,
    isSubtask: false,
    parentId: '',
    projectId,
    userId,
  })

  if (subtasks.length) {
    subtasks.forEach((el) => {
      const {title, text, deadlineDate, type} = el
      arr.push({
        id: uuidv4(),
        title,
        text,
        startDate: new Date(),
        deadlineDate,
        type,
        isSubtask: true,
        parentId,
      })
    })
  }
  try {
    const result = await Tasks.create(arr)
    res.status(200).json(result)
  } catch (e) {
    res.status(500).json({success: false, msg: e})
  }
}

const postNewSubTaskHandler = async (req, res) => {
  const {id} = req.params
  const {title, text, deadlineDate, type} = req.body

  try {
    const task = await Tasks.create({
      id: uuidv4(),
      title,
      text,
      startDate: new Date(),
      deadlineDate,
      type,
      isSubtask: true,
      parentId: id,
    })
    res.status(200).json(task)
  } catch (e) {
    res.status(500).json({success: false, msg: e})
  }
}

const putTasksHandler = async (req, res) => {
  const {id} = req.params
  const {task: nameChange, subtasks, removedSubtasks} = req.body
  const updatedTasks = subtasks?.filter((el) => el.id)
  const newTasks = []
  const newSubtasks = subtasks?.filter((el) => !el.id)
  if (newSubtasks.length) {
    newSubtasks.forEach((el) => {
      const {title, text, deadlineDate, type} = el
      newTasks.push({
        id: uuidv4(),
        title,
        text,
        startDate: new Date(),
        deadlineDate,
        type,
        isSubtask: true,
        parentId: id,
      })
    })
  }
  try {
    await Tasks.create(newTasks) //создали новые подзадачи
    if (removedSubtasks.length) {
      removedSubtasks.forEach(async (el) => await Tasks.deleteOne({id: el}))
    }
    if (updatedTasks.length) {
      updatedTasks.forEach(async (el) => await Tasks.findOneAndUpdate({id: el.id}, {$set: el}))
    }
    const task = await Tasks.findOneAndUpdate(
      {id: id},
      {$set: nameChange},
      {returnDocument: 'after'},
    )
    task
      ? res.status(200).json(task)
      : res.status(404).json({success: false, msg: 'Документы не найдены'})
  } catch (e) {
    res.status(500).json({success: false, msg: e})
  }
}

const patchAllTasksHandler = async (req, res) => {
  const {taskIds, updateFields} = req.body

  if (taskIds.length) {
    try {
      const bulkOps = taskIds.map((id) => ({
        updateOne: {
          filter: {id: id},
          update: {$set: {...updateFields}},
        },
      }))

      const result = await Tasks.bulkWrite(bulkOps)
      const updatedIds =
        result && result.modifiedCount > 0
          ? taskIds.filter((id, index) => result.modifiedCount > index)
          : []
      res.status(200).json(updatedIds)
    } catch (e) {
      res.status(500).json({success: false, msg: e})
    }
  }
}

const patchTaskHandler = async (req, res) => {
  const {id} = req.params
  const nameChange = req.body
  try {
    const task = await Tasks.findOneAndUpdate(
      {id: id},
      {$set: nameChange},
      {returnDocument: 'after'},
    )
    task
      ? res.status(200).json(task)
      : res.status(404).json({success: false, msg: 'Документы не найдены'})
  } catch (e) {
    res.status(500).json({success: false, msg: e})
  }
}

const deleteTaskHandler = async (req, res) => {
  const {id} = req.params
  const arr = [id]
  try {
    let count = 0
    const subTasks = await Tasks.find({parentId: id})
    if (subTasks.length) {
      subTasks.forEach((el) => arr.push(el.id))
      const resSubTasks = await Tasks.deleteMany({parentId: id})
      count += resSubTasks.deletedCount
    }
    const taskParent = await Tasks.deleteOne({id: id})
    count += taskParent.deletedCount
    count
      ? res.status(200).json({countDelete: count, tasksId: arr})
      : res.status(404).json({success: false, countDelete: count, msg: 'Документ уже удален'})
  } catch (e) {
    res.status(500).json({success: false, msg: e})
  }
}

module.exports = {
  getAllTasksHandler,
  getAllSubTasksHandler,
  getTaskHandler,
  getSubTaskHandler,
  postNewTaskHandler,
  postNewSubTaskHandler,
  putTasksHandler,
  patchAllTasksHandler,
  patchTaskHandler,
  deleteTaskHandler,
}
